package my12306;

import com.ywh.train.Constants;
import com.ywh.train.Util;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import my12306.bean.PassengerInfo;
import my12306.bean.QueryResult;
import my12306.bean.Seats;
import my12306.bean.Tokens;
import my12306.db.SQLite;
import my12306.http.Consts;
import my12306.http.TrainInfo;
import my12306.http.Utils;
import my12306.ocr.OCR;
import my12306.table.KeyValueItem;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 */
public class TrainClient implements IUpdateImage {

    private Logger log = LoggerFactory.getLogger(getClass());
    private HttpClient httpClient = null;
    private Random random;
    private String userAgent;
    private String currentUser;
    private String pwd;
    private final static ImageThread imageThread = My12306App.getImageThread();

    /**
     *
     */
    public TrainClient(HttpClient client) {
        this.httpClient = client;
        random = new Random(System.currentTimeMillis());
    }
    //<editor-fold defaultstate="collapsed" desc=" Randcode Dialog "> 
    private JLabel label;

    private synchronized JLabel getLabel() {
        if (label == null) {
            label = new JLabel("", JLabel.CENTER);
            label.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    imageThread.continueRun();
                }
            });
        }
        return label;
    }

    public String getRandCodeDailog(final String url) {
        imageThread.download(url);
        try {
            synchronized (imageThread) {
                imageThread.wait();
            }
        } catch (InterruptedException ex) {
        }
        return JOptionPane.showInputDialog(null, getLabel(), "请输入验证码", JOptionPane.DEFAULT_OPTION);
    }

    public TrainClient getTrainClient() {
        return this;
    }

    public void updateImage(byte[] image) {
        getLabel().setIcon(new ImageIcon(image));
        getLabel().setText(OCR.doOCR(image));
    }
    //</editor-fold> 

    public QueryResult doGet(String url) {
        QueryResult qr = new QueryResult();
        HttpGet get = null;
        try {
            get = getGet(url);
            String result = getHttpclient().execute(get, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(result);
            qr.setRawData(result);
            qr.setMsg(info);
            qr.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            qr.setState(QueryResult.FAIL);
            qr.setMsg(ex.getMessage());
            log.error(ex.getLocalizedMessage(), ex);
        } finally {
            if (get != null) {
                get.releaseConnection();
            }
        }
        return qr;
    }

    public QueryResult doPost(String url) {
        QueryResult qr = new QueryResult();
        try {
            HttpPost post = getPost(url);
            String result = getHttpclient().execute(post, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(result);

            log.debug(info);

            qr.setRawData(result);
            qr.setMsg(info);
            qr.setState(QueryResult.SUCC);
            post.releaseConnection();
        } catch (Exception ex) {
            qr.setState(QueryResult.FAIL);
            qr.setMsg(ex.getMessage());
            log.error(ex.getLocalizedMessage(), ex);
        }

        return qr;
    }

    public HttpGet getGet(String url) {
        HttpGet get = new HttpGet(url);
        get.addHeader(HTTP.USER_AGENT, getUserAgent());
        return get;
    }

    public HttpPost getPost(String url) {
        HttpPost post = new HttpPost(url);
        post.addHeader(HTTP.USER_AGENT, getUserAgent());
        return post;
    }

    /**
     * extract ticket info from response html ticket format: <input
     * type="hidden" name="leftTicketStr" id="left_ticket"
     * value="10192031234059900003101920005061103000123033900040" /> <input
     * type="hidden" name="org.apache.struts.taglib.html.TOKEN"
     * value="c7a2dbcec357f3810eaf29e1dd1cefd1">
     *
     * @return ticket
     */
    public Tokens getTokensFromUrl() {
        Tokens tokens = new Tokens();
        try {
            QueryResult qr = doGet(Consts.URL_ConfirmPassengerAction_init);
            tokens = getTokensFromHtml(qr.getRawData());
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return tokens;
    }

    public Tokens getTokensFromHtml(String input) {
        String ticket = "";
        String token = "";
        String bedlevel = "";
        Tokens tokens = new Tokens();
        try {
            String ticketPattern = "name=\"leftTicketStr\" id=\"left_ticket\"\\x0d\\x0a\\x09value=\"([A-Za-z\\d]{20,})\"";
            String tokenPattern = "name=\"org.apache.struts.taglib.html.TOKEN\" value=\"([A-Za-z\\d]{30,})\"";
            String bedLevelPattern = "name=\"orderRequest.bed_level_order_num\" value=\"([A-Za-z\\d]{30,})\"";

            Matcher matcherTicket = Pattern.compile(ticketPattern).matcher(input);
            if (matcherTicket.find()) {
                ticket = matcherTicket.group(1);
//                log.info("ticket: {}", ticket);
            } else {
                log.info("ticket: {}", "not found.");
            }
            Matcher matcherToken = Pattern.compile(tokenPattern).matcher(input);
            if (matcherToken.find()) {
                token = matcherToken.group(1);
//                log.info("token: {}", token);
            } else {
                log.info("token: {}", "not found.");
            }
            Matcher matcherBedlevel = Pattern.compile(bedLevelPattern).matcher(input);
            if (matcherBedlevel.find()) {
                bedlevel = matcherBedlevel.group(1);
//                log.info("bedlevel: {}", bedlevel);
            } else {
                log.info("bedlevel: {}", "not found.");
            }
            tokens.setBedlevel(bedlevel);
            tokens.setTicket(ticket);
            tokens.setToken(token);
            log.info(token);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }

        return tokens;
    }

    //<editor-fold defaultstate="collapsed" desc=" confirm methods "> 
    public QueryResult confirmPassengerAction_init() {
        log.debug("-----------------confirmPassengerAction_init start-----------------------");
        QueryResult rs = new QueryResult();
        HttpGet get = getGet(Consts.URL_ConfirmPassengerAction_init);
        get.addHeader(Consts.Accept_Header, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
        get.addHeader(Consts.Connection_Header, Consts.Connection);
        get.addHeader(Consts.Host_Header, Consts.Host);
        get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=init");
        //get.addHeader("Cookie", getCookies());
        try {
            String responseBody = getHttpclient().execute(get, new BasicResponseHandler());
            rs.setTokens(getTokensFromHtml(responseBody));
            String info = Util.removeTagFromHtml(responseBody);
            log.debug(info);
            rs.setMsg(info);
            rs.setRawData(responseBody);
            rs.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            rs.setMsg(ex.getLocalizedMessage());
            rs.setRawData(ex.getLocalizedMessage());
            rs.setState(QueryResult.SUCC);
            log.error(ex.getMessage(), ex);
        } finally {
            get.releaseConnection();
        }
        log.debug("-------------------confirmPassengerAction_init end---------------------");
        return rs;
    }

    public QueryResult confirmPassengerAction_getpassengerJson() {
        log.debug("-------------------confirmPassengerAction_getpassengerJson start-------------------");
        QueryResult qr = new QueryResult();
        if (!isLoginOk()) {
            log.debug("not login.");
            qr = new QueryResult();
            qr.setMsg("not login.");
            qr.setState(QueryResult.FAIL);
            return qr;
        }

        HttpPost post = null;
        try {
            post = getPost(Consts.URL_ConfirmPassengerAction_getpassengerJson);
            post.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//            post.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            post.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            post.addHeader("Cache-Control", "no-cache");
            post.addHeader(Consts.Connection_Header, Consts.Connection);
            post.addHeader("Content-Type", "application/x-www-form-urlencoded");
            post.addHeader(Consts.Host_Header, Consts.Host);
            post.addHeader("Pragma", "no-cache");
            post.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
            post.addHeader("X-Requested-With", "XMLHttpRequest");
            //post.addHeader("Cookie", getCookies());

            String result = getHttpclient().execute(post, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(result);

            qr.setRawData(result);
            qr.setMsg(info);
            qr.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            qr.setState(QueryResult.FAIL);
            qr.setMsg(ex.getMessage());
            log.error(ex.getLocalizedMessage(), ex);
        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
        log.debug("-------------------confirmPassengerAction_getpassengerJson end-------------------");
        return qr;
    }

    public QueryResult confirmPassengerAction_checkOrderInfo_step2_1(String randCode, Tokens tokens,
            List<PassengerInfo> users, TrainInfo train) {
        log.debug("-------------------confirmPassengerAction_checkOrderInfo order start-------------------");
        QueryResult rs = new QueryResult();
        HttpPost post = getPost(Consts.URL_ConfirmPassengerAction_checkOrderInfo + randCode);
        post.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//            post.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            post.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
        post.addHeader("Cache-Control", "no-cache");
        post.addHeader(Consts.Connection_Header, Consts.Connection);
        post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        post.addHeader(Consts.Host_Header, Consts.Host);
        post.addHeader("Pragma", "no-cache");
        post.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
        post.addHeader("X-Requested-With", "XMLHttpRequest");
        //post.addHeader("Cookie", getCookies());

        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (int i = 0; i < users.size(); i++) {
            formparams.add(new BasicNameValuePair("checkbox" + i, "" + i));
        }
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));

        formparams.add(new BasicNameValuePair("leftTicketStr", tokens.getTicket()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("oldPassengers", user.getSimpleText()));
        }
        for (int i = users.size(); i < 5; i++) {
            formparams.add(new BasicNameValuePair("oldPassengers", ""));
        }

        formparams.add(new BasicNameValuePair("orderRequest.bed_level_order_num", tokens.getBedlevel()));
        formparams.add(new BasicNameValuePair("orderRequest.cancel_flag", "1"));
        formparams.add(new BasicNameValuePair("orderRequest.end_time", train.getMeta().getArrive_time())); //"09:00"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_name", train.getMeta().getFrom_station_name())); //"广州"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_telecode", train.getMeta().getFrom_station_telecode())); //"GZQ"
        formparams.add(new BasicNameValuePair("orderRequest.id_mode", "Y")); //"Y"
        formparams.add(new BasicNameValuePair("orderRequest.reserve_flag", "A"));
        formparams.add(new BasicNameValuePair("orderRequest.seat_type_code", ""));

        formparams.add(new BasicNameValuePair("orderRequest.start_time", train.getMeta().getTrain_start_time()));//"12:12"
        formparams.add(new BasicNameValuePair("orderRequest.station_train_code", train.getMeta().getStation_train_code())); //"L32"
        formparams.add(new BasicNameValuePair("orderRequest.ticket_type_order_num", ""));
        formparams.add(new BasicNameValuePair("orderRequest.to_station_name", train.getMeta().getTo_station_name())); //"郑州"
        formparams.add(new BasicNameValuePair("orderRequest.to_station_telecode", train.getMeta().getTo_station_telecode())); //"ZZF"
        formparams.add(new BasicNameValuePair("orderRequest.train_date", train.getStartDate()));  //"2013-01-26"        
        formparams.add(new BasicNameValuePair("orderRequest.train_no", train.getMeta().getTrainno())); // "6300000L3210"
        formparams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", tokens.getToken()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("passengerTickets", user.getTickets()));
        }

        for (int i = 1; i <= users.size(); i++) {
            PassengerInfo user = users.get(i - 1);
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardno", user.getID())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardtype", user.getIDType())); //"1"
            formparams.add(new BasicNameValuePair("passenger_" + i + "_mobileno", user.getPhone())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_name", user.getName()));
            formparams.add(new BasicNameValuePair("passenger_" + i + "_seat", user.getSeatType())); //席别
            formparams.add(new BasicNameValuePair("passenger_" + i + "_ticket", user.getTickType())); //车票类型
        }

        formparams.add(new BasicNameValuePair("randCode", randCode));
        formparams.add(new BasicNameValuePair("tFlag", "dc"));
        formparams.add(new BasicNameValuePair("textfield", "中文或拼音首字母"));
        String responseBody = null;
        try {
            UrlEncodedFormEntity uef = new UrlEncodedFormEntity(formparams, HTTP.UTF_8);
            post.setEntity(uef);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            responseBody = getHttpclient().execute(post, responseHandler);

            String info = Util.removeTagFromHtml(responseBody);
            log.info("checkOrderInfo result: {}", info);

            rs.setState(QueryResult.SUCC);
            rs.setMsg(info);
            rs.setRawData(responseBody);
            String ans = Util.getMessageFromHtml(responseBody);
            log.debug(ans);
            post.releaseConnection();
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            rs.setMsg(ex.getMessage());
            rs.setState(QueryResult.FAIL);
        }
        log.debug("-------------------confirmPassengerAction_checkOrderInfo order end-------------------");
        return rs;
    }

    public QueryResult confirmPassengerAction_getQueueCount_step2_2(TrainInfo bestTrain, String seatType, String ticket) {
        QueryResult qr = new QueryResult();
        try {
            log.debug("-------------------confirmPassengerAction_getQueueCount start-------------------");
            List<NameValuePair> parameters = new ArrayList<NameValuePair>();
            parameters.add(new BasicNameValuePair("train_date", bestTrain.getStartDate()));
            parameters.add(new BasicNameValuePair("train_no", bestTrain.getMeta().getTrainno())); //6300000L3210
            parameters.add(new BasicNameValuePair("station", bestTrain.getMeta().getStation_train_code()));//L32
            parameters.add(new BasicNameValuePair("seat", seatType));
            parameters.add(new BasicNameValuePair("from", bestTrain.getMeta().getFrom_station_telecode()));
            parameters.add(new BasicNameValuePair("to", bestTrain.getMeta().getTo_station_telecode()));
            parameters.add(new BasicNameValuePair("ticket", ticket));
            HttpGet get = getGet(Consts.URL_ConfirmPassengerAction_getQueueCount + URLEncodedUtils.format(parameters, HTTP.UTF_8));

            get.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//            get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader("Content-Type", "application/x-www-form-urlencoded");
            get.addHeader(Consts.Host_Header, Consts.Host);
            get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
            get.addHeader("X-Requested-With", "XMLHttpRequest");
            //get.addHeader("Cookie", getCookies());

            String result = getHttpclient().execute(get, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(result);

            log.info("getQueueCount result: {}", info);

            qr.setRawData(result);
            qr.setMsg(info);
            qr.setState(QueryResult.SUCC);
            get.releaseConnection();
        } catch (Exception ex) {
            qr.setState(QueryResult.FAIL);
            qr.setMsg(ex.getMessage());
            log.error(ex.getLocalizedMessage(), ex);
        }
        log.debug("-------------------confirmPassengerAction_getQueueCount end-------------------");
        return qr;
    }

    public QueryResult confirmPassengerAction_confirmSingleForQueueOrder_step3_1(String randCode,
            Tokens tokens, List<PassengerInfo> users, TrainInfo train) {
        log.debug("-------------------step3_1 start-------------------");
        QueryResult rs = new QueryResult();
        HttpPost post = getPost(Consts.URL_ConfirmPassengerAction_confirmSingleForQueue);

        post.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//            post.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            post.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
        post.addHeader("Cache-Control", "no-cache");
        post.addHeader(Consts.Connection_Header, Consts.Connection);
        post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        post.addHeader(Consts.Host_Header, Consts.Host);
        post.addHeader("Pragma", "no-cache");
        post.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
        post.addHeader("X-Requested-With", "XMLHttpRequest");
        //post.addHeader("Cookie", getCookies());

        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (int i = 0; i < users.size(); i++) {
            formparams.add(new BasicNameValuePair("checkbox" + i, "" + i));
        }
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));

        formparams.add(new BasicNameValuePair("leftTicketStr", tokens.getTicket()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("oldPassengers", user.getSimpleText()));
        }
        for (int i = users.size(); i < 5; i++) {
            formparams.add(new BasicNameValuePair("oldPassengers", ""));
        }

        formparams.add(new BasicNameValuePair("orderRequest.bed_level_order_num", tokens.getBedlevel()));
        formparams.add(new BasicNameValuePair("orderRequest.cancel_flag", "1"));
        formparams.add(new BasicNameValuePair("orderRequest.end_time", train.getMeta().getArrive_time())); //"09:00"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_name", train.getMeta().getFrom_station_name())); //"广州"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_telecode", train.getMeta().getFrom_station_telecode())); //"GZQ"
        formparams.add(new BasicNameValuePair("orderRequest.id_mode", "Y")); //"Y"
        formparams.add(new BasicNameValuePair("orderRequest.reserve_flag", "A"));
        formparams.add(new BasicNameValuePair("orderRequest.seat_type_code", ""));

        formparams.add(new BasicNameValuePair("orderRequest.start_time", train.getMeta().getTrain_start_time()));//"12:12"
        formparams.add(new BasicNameValuePair("orderRequest.station_train_code", train.getMeta().getStation_train_code())); //"L32"
        formparams.add(new BasicNameValuePair("orderRequest.ticket_type_order_num", ""));
        formparams.add(new BasicNameValuePair("orderRequest.to_station_name", train.getMeta().getTo_station_name())); //"郑州"
        formparams.add(new BasicNameValuePair("orderRequest.to_station_telecode", train.getMeta().getTo_station_telecode())); //"ZZF"
        formparams.add(new BasicNameValuePair("orderRequest.train_date", train.getStartDate()));  //"2013-01-26"
        formparams.add(new BasicNameValuePair("orderRequest.train_no", train.getMeta().getTrainno())); // "6300000L3210"
        formparams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", tokens.getToken()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("passengerTickets", user.getTickets()));
        }

        for (int i = 1; i <= users.size(); i++) {
            PassengerInfo user = users.get(i - 1);
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardno", user.getID())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardtype", user.getIDType())); //"1"
            formparams.add(new BasicNameValuePair("passenger_" + i + "_mobileno", user.getPhone())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_name", user.getName()));
            formparams.add(new BasicNameValuePair("passenger_" + i + "_seat", user.getSeatType())); //席别
            formparams.add(new BasicNameValuePair("passenger_" + i + "_ticket", user.getTickType())); //车票类型
        }

        formparams.add(new BasicNameValuePair("randCode", randCode));
//        formparams.add(new BasicNameValuePair("tFlag", "dc"));    //no tFlag
        formparams.add(new BasicNameValuePair("textfield", "中文或拼音首字母"));
        String responseBody = null;
        try {
            UrlEncodedFormEntity uef = new UrlEncodedFormEntity(formparams, HTTP.UTF_8);
            post.setEntity(uef);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            responseBody = getHttpclient().execute(post, responseHandler);

            String info = Util.removeTagFromHtml(responseBody);
            log.info("confirmSingleForQueueOrder result: {}", info);
            rs.setRawData(responseBody);
            rs.setMsg(info);
            rs.setState(QueryResult.SUCC);
            post.releaseConnection();
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            rs.setMsg(ex.getMessage());
            rs.setState(QueryResult.FAIL);
        }
        log.debug("-------------------step3_1 end-------------------");
        return rs;
    }

    public QueryResult confirmPassengerAction_cancel(String randCode,
            Tokens tokens, List<PassengerInfo> users, TrainInfo train) {
        log.debug("-------------------confirmPassengerAction_cancel start-------------------");
        QueryResult rs = new QueryResult();
        HttpPost post = getPost(Consts.URL_ConfirmPassengerAction_cancel);

        post.addHeader(Consts.Accept_Header, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//            post.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            post.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
        post.addHeader(Consts.Connection_Header, Consts.Connection);
        post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        post.addHeader(Consts.Host_Header, Consts.Host);
        post.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
        //post.addHeader("Cookie", getCookies());
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (int i = 0; i < users.size(); i++) {
            formparams.add(new BasicNameValuePair("checkbox" + i, "" + i));
        }
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));

        formparams.add(new BasicNameValuePair("leftTicketStr", tokens.getTicket()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("oldPassengers", user.getSimpleText()));
        }
        for (int i = users.size(); i < 5; i++) {
            formparams.add(new BasicNameValuePair("oldPassengers", ""));
        }

        formparams.add(new BasicNameValuePair("orderRequest.bed_level_order_num", tokens.getBedlevel()));
        formparams.add(new BasicNameValuePair("orderRequest.cancel_flag", "1"));
        formparams.add(new BasicNameValuePair("orderRequest.end_time", train.getMeta().getArrive_time())); //"09:00"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_name", train.getMeta().getFrom_station_name())); //"广州"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_telecode", train.getMeta().getFrom_station_telecode())); //"GZQ"
        formparams.add(new BasicNameValuePair("orderRequest.id_mode", "Y")); //"Y"
        formparams.add(new BasicNameValuePair("orderRequest.reserve_flag", "A"));
        formparams.add(new BasicNameValuePair("orderRequest.seat_type_code", ""));

        formparams.add(new BasicNameValuePair("orderRequest.start_time", train.getMeta().getTrain_start_time()));//"12:12"
        formparams.add(new BasicNameValuePair("orderRequest.station_train_code", train.getMeta().getStation_train_code())); //"L32"
        formparams.add(new BasicNameValuePair("orderRequest.ticket_type_order_num", ""));
        formparams.add(new BasicNameValuePair("orderRequest.to_station_name", train.getMeta().getTo_station_name())); //"郑州"
        formparams.add(new BasicNameValuePair("orderRequest.to_station_telecode", train.getMeta().getTo_station_telecode())); //"ZZF"
        formparams.add(new BasicNameValuePair("orderRequest.train_date", train.getStartDate()));  //"2013-01-26"
        formparams.add(new BasicNameValuePair("orderRequest.train_no", train.getMeta().getTrainno())); // "6300000L3210"
        formparams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", tokens.getToken()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("passengerTickets", user.getTickets()));
        }

        for (int i = 1; i <= users.size(); i++) {
            PassengerInfo user = users.get(i - 1);
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardno", user.getID())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardtype", user.getIDType())); //"1"
            formparams.add(new BasicNameValuePair("passenger_" + i + "_mobileno", user.getPhone())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_name", user.getName()));
            formparams.add(new BasicNameValuePair("passenger_" + i + "_seat", user.getSeatType())); //席别
            formparams.add(new BasicNameValuePair("passenger_" + i + "_ticket", user.getTickType())); //车票类型
        }

        formparams.add(new BasicNameValuePair("randCode", randCode));
//        formparams.add(new BasicNameValuePair("tFlag", "dc"));    //no tFlag
        formparams.add(new BasicNameValuePair("textfield", "中文或拼音首字母"));
        String responseBody = null;
        try {
            UrlEncodedFormEntity uef = new UrlEncodedFormEntity(formparams, HTTP.UTF_8);
            post.setEntity(uef);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            responseBody = getHttpclient().execute(post, responseHandler);

            String info = Util.removeTagFromHtml(responseBody);
            log.info("confirmPassengerAction_cancel result: {}", info);
            rs.setRawData(responseBody);
            rs.setMsg(info);
            rs.setState(QueryResult.SUCC);
            post.releaseConnection();
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            rs.setMsg(ex.getMessage());
            rs.setState(QueryResult.FAIL);
        }
        log.debug("-------------------confirmPassengerAction_cancel end-------------------");
        return rs;
    }

    public QueryResult myOrderAction_getOrderWaitTime_3_2(TrainInfo bestTrain, String seatType, String ticket) {
        QueryResult qr = new QueryResult();
        HttpGet get = null;
        try {
            log.debug("-------------------myOrderAction_getOrderWaitTime_3_2 start-------------------");
            get = getGet(Consts.URL_MyOrderAction_queryOrderWaitTime);

            get.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//            get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader("Content-Type", "application/x-www-form-urlencoded");
            get.addHeader(Consts.Host_Header, Consts.Host);
            get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
            get.addHeader("X-Requested-With", "XMLHttpRequest");

            String result = getHttpclient().execute(get, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(result);

            log.info("getOrderWaitTime result: {}", info);

            qr.setRawData(result);
            qr.setMsg(info);
            qr.setState(QueryResult.SUCC);

        } catch (Exception ex) {
            qr.setState(QueryResult.FAIL);
            qr.setMsg(ex.getMessage());
            log.error(ex.getLocalizedMessage(), ex);
        } finally {
            if (get != null) {
                get.releaseConnection();
            }
        }
        log.debug("-------------------myOrderAction_getOrderWaitTime_3_2 end-------------------");
        return qr;
    }

    public QueryResult confirmPassengerAction_payOrder_step3_4(String orderid, String randCode, Tokens tokens, List<PassengerInfo> users, TrainInfo train) {
        log.debug("-------------------confirmPassengerAction_payOrder_step3_4 start-------------------");
        QueryResult rs = new QueryResult();
        HttpPost post = null;
        post = getPost(Consts.URL_ConfirmPassengerAction_payOrder + orderid);
        post.addHeader(Consts.Accept_Header, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//            post.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//            post.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
//        post.addHeader("Cache-Control", "no-cache");
        post.addHeader(Consts.Connection_Header, Consts.Connection);
        post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        post.addHeader(Consts.Host_Header, Consts.Host);
//        post.addHeader("Pragma", "no-cache");
        post.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
        post.addHeader("X-Requested-With", "XMLHttpRequest");

        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (int i = 0; i < users.size(); i++) {
            formparams.add(new BasicNameValuePair("checkbox" + i, "" + i));
        }
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));
        formparams.add(new BasicNameValuePair("checkbox9", "Y"));

        formparams.add(new BasicNameValuePair("leftTicketStr", tokens.getTicket()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("oldPassengers", user.getSimpleText()));
        }
        for (int i = users.size(); i < 5; i++) {
            formparams.add(new BasicNameValuePair("oldPassengers", ""));
        }

        formparams.add(new BasicNameValuePair("orderRequest.bed_level_order_num", tokens.getBedlevel()));
        formparams.add(new BasicNameValuePair("orderRequest.cancel_flag", "1"));
        formparams.add(new BasicNameValuePair("orderRequest.end_time", train.getMeta().getArrive_time())); //"09:00"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_name", train.getMeta().getFrom_station_name())); //"广州"
        formparams.add(new BasicNameValuePair("orderRequest.from_station_telecode", train.getMeta().getFrom_station_telecode())); //"GZQ"
        formparams.add(new BasicNameValuePair("orderRequest.id_mode", "Y")); //"Y"
        formparams.add(new BasicNameValuePair("orderRequest.reserve_flag", "A"));
        formparams.add(new BasicNameValuePair("orderRequest.seat_type_code", ""));

        formparams.add(new BasicNameValuePair("orderRequest.start_time", train.getMeta().getTrain_start_time()));//"12:12"
        formparams.add(new BasicNameValuePair("orderRequest.station_train_code", train.getMeta().getStation_train_code())); //"L32"
        formparams.add(new BasicNameValuePair("orderRequest.ticket_type_order_num", ""));
        formparams.add(new BasicNameValuePair("orderRequest.to_station_name", train.getMeta().getTo_station_name())); //"郑州"
        formparams.add(new BasicNameValuePair("orderRequest.to_station_telecode", train.getMeta().getTo_station_telecode())); //"ZZF"
        formparams.add(new BasicNameValuePair("orderRequest.train_date", train.getStartDate()));  //"2013-01-26"
        formparams.add(new BasicNameValuePair("orderRequest.train_no", train.getMeta().getTrainno())); // "6300000L3210"
        formparams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", tokens.getToken()));

        for (PassengerInfo user : users) {
            formparams.add(new BasicNameValuePair("passengerTickets", user.getTickets()));
        }

        for (int i = 1; i <= users.size(); i++) {
            PassengerInfo user = users.get(i - 1);
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardno", user.getID())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_cardtype", user.getIDType())); //"1"
            formparams.add(new BasicNameValuePair("passenger_" + i + "_mobileno", user.getPhone())); //
            formparams.add(new BasicNameValuePair("passenger_" + i + "_name", user.getName()));
            formparams.add(new BasicNameValuePair("passenger_" + i + "_seat", user.getSeatType())); //席别
            formparams.add(new BasicNameValuePair("passenger_" + i + "_ticket", user.getTickType())); //车票类型
        }

        formparams.add(new BasicNameValuePair("randCode", randCode));
        //        formparams.add(new BasicNameValuePair("tFlag", "dc"));    //no tFlag
        formparams.add(new BasicNameValuePair("textfield", "中文或拼音首字母"));
        String responseBody = null;
        try {
            UrlEncodedFormEntity uef = new UrlEncodedFormEntity(formparams, HTTP.UTF_8);
            post.setEntity(uef);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            responseBody = getHttpclient().execute(post, responseHandler);

            String info = Util.removeTagFromHtml(responseBody);
            log.info("payOrder result: {}", info);
            rs.setRawData(responseBody);
            rs.setMsg(info);
            rs.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            rs.setMsg(ex.getMessage());
            rs.setState(QueryResult.FAIL);
            log.error(ex.getLocalizedMessage(), ex);
        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
        log.debug("-------------------confirmPassengerAction_payOrder_step3_4 end-------------------");
        return rs;
    }

    public List<List<Object>> getPassengerData() throws JSONException {
        List<List<Object>> data = new ArrayList<List<Object>>();
        org.json.JSONObject json = new org.json.JSONObject(confirmPassengerAction_getpassengerJson().getRawData());
        JSONArray array = (JSONArray) json.get("passengerJson");
        int len = array.length() > 5 ? 5 : array.length();
        for (int i = 0; i < len; i++) {
            org.json.JSONObject obj = (org.json.JSONObject) array.get(i);
            List<Object> row = new ArrayList<Object>();
            row.add(Integer.toString(i + 1));
            row.add(Seats.getSeat("1"));
            row.add(KeyValueItem.getTicketType(obj.getString("passenger_type")));
            row.add(obj.getString("passenger_name"));
            row.add(KeyValueItem.getIDType(obj.getString("passenger_id_type_code")));
            row.add(obj.getString("passenger_id_no"));
            row.add(obj.getString("mobile_no"));
            data.add(row);
        }
        return data;
    }

    //</editor-fold> 
    //<editor-fold defaultstate="collapsed" desc=" query methods "> 
    public QueryResult querySingleAction_init() {
        log.debug("-----------------querySingleAction_init start-----------------------");
        QueryResult rs = new QueryResult();
        HttpGet get = null;

        try {
            get = getGet(Consts.URL_QuerySingleAction_init);
//        get.addHeader(Consts.Accept_Header, Consts.Accept);
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
            get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader(Consts.Host_Header, Consts.Host);
            get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/main.jsp");
            //get.addHeader("Cookie", getCookies());

            String responseBody = getHttpclient().execute(get, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(responseBody);
//            log.debug(info);

            rs.setMsg(info);
            rs.setRawData(responseBody);
            rs.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        } finally {
            get.releaseConnection();
        }
        log.debug("-------------------querySingleAction_init end---------------------");
        return rs;
    }

    /**
     * 查询列车信息
     *
     * @param from
     * @param to
     * @param startDate
     * @param startTime
     * @return
     */
    public QueryResult querySingleAction_queryLeftTicket(String from,
            String to, String startDate, String startTime, String trainno) {
        return querySingleAction_queryLeftTicket(from, to, startDate, startTime, trainno, "");
    }

    public QueryResult querySingleAction_queryLeftTicket(String from,
            String to, String startDate, String startTime, String trainno, String trainClass) {
        log.debug("-------------------query train start-------------------");
        if (startTime == null || startTime.isEmpty()) {
            startTime = "00:00--24:00";
        }
        if (trainno == null || trainno.isEmpty()) {
            trainno = "";
        }
        if (trainClass == null || trainClass.isEmpty()) {
            trainClass = "QB#D#Z#T#K#QT#";
        }
        List<NameValuePair> parameters = new ArrayList<NameValuePair>();
//        parameters.add(new BasicNameValuePair("method", "queryLeftTicket"));
        parameters.add(new BasicNameValuePair("orderRequest.train_date", startDate));
//        parameters.add(new BasicNameValuePair("orderRequest.from_station_telecode", Util.getCityCode(from)));
//        parameters.add(new BasicNameValuePair("orderRequest.to_station_telecode", Util.getCityCode(to)));
        parameters.add(new BasicNameValuePair("orderRequest.from_station_telecode", SQLite.getCityCode(from)));
        parameters.add(new BasicNameValuePair("orderRequest.to_station_telecode", SQLite.getCityCode(to)));
        
        parameters.add(new BasicNameValuePair("orderRequest.train_no", trainno));
        parameters.add(new BasicNameValuePair("trainPassType", "QB"));
        parameters.add(new BasicNameValuePair("trainClass", trainClass));//"QB#D#Z#T#K#QT#"
        parameters.add(new BasicNameValuePair("includeStudent", "00"));
        parameters.add(new BasicNameValuePair("seatTypeAndNum", ""));
        parameters.add(new BasicNameValuePair("orderRequest.start_time_str", startTime));

        HttpGet get = null;
        QueryResult qr = new QueryResult();

        HashMap<String, TrainInfo> all = null;
        try {
            get = getGet(Consts.URL_QuerySingleAction_queryLeftTicket + URLEncodedUtils.format(parameters, HTTP.UTF_8));

            get.addHeader(Consts.Accept_Header, "text/plain, */*");
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader("Content-Type", "application/x-www-form-urlencoded");
            get.addHeader(Consts.Host_Header, Consts.Host);
            get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=init");
            get.addHeader("X-Requested-With", "XMLHttpRequest");
            //get.addHeader("Cookie", getCookies());

            String responseBody = getHttpclient().execute(get, new BasicResponseHandler());

            all = Utils.parserTrainInfo(responseBody, startDate);
            qr.setMsg(responseBody);
            qr.setRawData(responseBody);
            qr.setState(QueryResult.SUCC);
            qr.setTrains(all);

        } catch (Exception ex) {
            qr.setMsg(ex.getLocalizedMessage());
            qr.setRawData(ex.toString());
            qr.setState(QueryResult.FAIL);
            log.error(ex.getMessage(), ex);
        } finally {
            get.releaseConnection();
        }
        log.debug("-------------------query train end-------------------");
        return qr;

    }

    public QueryResult querySingleAction_queryTrainStopTimeByTrainNo(String depart_date, String from, String to, String train_no) {
        log.debug("-------------------getTrainInfo start-------------------");
        QueryResult qr = new QueryResult();
        List<NameValuePair> parameters = new ArrayList<NameValuePair>();
        parameters.add(new BasicNameValuePair("depart_date", depart_date));
//        parameters.add(new BasicNameValuePair("method", "queryaTrainStopTimeByTrainNo"));
        parameters.add(new BasicNameValuePair("from_station_telecode", from));
        parameters.add(new BasicNameValuePair("to", to));
        parameters.add(new BasicNameValuePair("train_no", train_no));

        HttpGet get = null;

        try {
            get = getGet(Consts.URL_QuerySingleAction_queryaTrainStopTimeByTrainNo
                    + URLEncodedUtils.format(parameters, HTTP.UTF_8));

            get.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader("Content-Type", "application/x-www-form-urlencoded");
            get.addHeader(Consts.Host_Header, Consts.Host);
            get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=init");
            get.addHeader("X-Requested-With", "XMLHttpRequest");
            //get.addHeader("Cookie", getCookies());


            String responseBody = getHttpclient().execute(get, new BasicResponseHandler());

            qr.setMsg(responseBody);
            qr.setRawData(responseBody);
            qr.setResult(Utils.getTrainStopTimeData(responseBody));
            qr.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            qr.setMsg(ex.getLocalizedMessage());
            qr.setRawData(ex.getLocalizedMessage());
            qr.setState(QueryResult.FAIL);
            log.error(ex.getMessage(), ex);
        } finally {
            get.releaseConnection();
        }

        log.debug("-------------------getTrainInfo end-------------------");
        return qr;
    }

    public QueryResult querySingleAction_submutOrderRequest_step1_1(String rangDate, TrainInfo train) {
        log.debug("-------------------querySingleAction_submutOrderRequest_step1_1 start-------------------");
        QueryResult qr = new QueryResult();
        HttpPost post = getPost(Consts.URL_QuerySingleAction_submutOrderRequest);

        post.addHeader(Consts.Accept_Header, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//        post.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        post.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
        post.addHeader(Consts.Connection_Header, Consts.Connection);
        post.addHeader(Consts.Host_Header, Consts.Host);
        post.addHeader("Referer", "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=init");
        //post.addHeader("Cookie", getCookies());

        List<NameValuePair> formparams = new ArrayList<NameValuePair>();

        formparams.add(new BasicNameValuePair("arrive_time", train.getMeta().getArrive_time()));//"09:15" 
        formparams.add(new BasicNameValuePair("from_station_name", train.getMeta().getFrom_station_name()));//"广州东"
        formparams.add(new BasicNameValuePair("from_station_no", train.getMeta().getFrom_station_no()));//"02"
        formparams.add(new BasicNameValuePair("from_station_telecode", train.getMeta().getFrom_station_telecode())); //"GGQ"
        formparams.add(new BasicNameValuePair("from_station_telecode_name", train.getMeta().getFrom_station_name()));//"上海"
        formparams.add(new BasicNameValuePair("include_student", "00"));
        formparams.add(new BasicNameValuePair("lishi", train.getMeta().getLishi())); //"15:10"
        formparams.add(new BasicNameValuePair("locationCode", train.getMeta().getLocationCode())); //"Q6"
        formparams.add(new BasicNameValuePair("mmStr", train.getMeta().getMmStr()));//"4DD86E4FE24AE1E0EE4A5F19ADE36A1C0B03FC7D961E7CA40B73A843"
        formparams.add(new BasicNameValuePair("round_start_time_str", rangDate)); //"00:00--24:00"
        formparams.add(new BasicNameValuePair("round_train_date", train.getStartDate())); //"2011-11-23"
        formparams.add(new BasicNameValuePair("seattype_num", ""));
        formparams.add(new BasicNameValuePair("single_round_type", "1"));
        formparams.add(new BasicNameValuePair("start_time_str", rangDate)); //"00:00--24:00"
        formparams.add(new BasicNameValuePair("station_train_code", train.getMeta().getStation_train_code())); //"T98"
        formparams.add(new BasicNameValuePair("to_station_name", train.getMeta().getTo_station_name())); //"郑州"
        formparams.add(new BasicNameValuePair("to_station_no", train.getMeta().getTo_station_no())); //"05"   
        formparams.add(new BasicNameValuePair("to_station_telecode", train.getMeta().getTo_station_telecode())); //"ZZF"
        formparams.add(new BasicNameValuePair("to_station_telecode_name", train.getMeta().getTo_station_name())); //"郑州"
        formparams.add(new BasicNameValuePair("train_class_arr", "QB#D#Z#T#K#QT#"));
        formparams.add(new BasicNameValuePair("train_date", train.getStartDate())); //"2011-11-28"
        formparams.add(new BasicNameValuePair("train_pass_type", "QB"));
        formparams.add(new BasicNameValuePair("train_start_time", train.getMeta().getTrain_start_time())); //"18:05"        
        formparams.add(new BasicNameValuePair("trainno4", train.getMeta().getTrainno())); //"6500000T9811"        
        formparams.add(new BasicNameValuePair("ypInfoDetail", train.getMeta().getYpInfoDetail())); //"1*****30631*****01223*****0051"        


        BufferedReader br = null;
        String responseBody = null;
        try {
            UrlEncodedFormEntity uef = new UrlEncodedFormEntity(formparams, HTTP.UTF_8);
            post.setEntity(uef);

            responseBody = getHttpclient().execute(post, new BasicResponseHandler());

            String info = Util.removeTagFromHtml(responseBody);
            log.info("submutOrderRequest result: {}", info);
            qr.setRawData(responseBody);
            qr.setMsg(info);
            qr.setState(QueryResult.SUCC);

            if (info.contains("系统忙")) {
                qr.setState(QueryResult.FAIL);
                qr.setMsg("系统忙");
            } else {
                qr.setState(QueryResult.SUCC);
                qr.setMsg(info);
            }
            post.releaseConnection();
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            qr.setMsg(ex.getMessage());
            qr.setState(QueryResult.FAIL);
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException ex) {
                log.error(ex.getMessage(), ex);
            }
        }
        log.debug("-------------------querySingleAction_submutOrderRequest_step1_1 end-------------------");
        return qr;

    }
    //</editor-fold> 

    //<editor-fold defaultstate="collapsed" desc=" Login methods ">  
    /**
     * init https://dynamic.12306.cn/otsweb/main.jsp get
     *
     * @return
     */
    public QueryResult loginInit() {
        log.debug("-----------------loginInit start-----------------------");
        QueryResult rs = new QueryResult();
        HttpGet get = null;

        try {
            get = getGet(Consts.URL_Login_main);
//        get.addHeader(Consts.Accept_Header, Consts.Accept);
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
            get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader(Consts.Host_Header, Consts.Host);
//            get.addHeader("Referer", "https://dynamic.12306.cn/otsweb/main.jsp");

            String responseBody = getHttpclient().execute(get, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(responseBody);
//            log.debug(info);

//            log.info(info);
            rs.setMsg(info);
            rs.setRawData(responseBody);
            rs.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        } finally {
            get.releaseConnection();
        }
        log.debug("-------------------loginInit end---------------------");
        return rs;
    }

    /**
     * https://dynamic.12306.cn/otsweb/loginAction.do?method=init
     *
     * @return
     */
    public QueryResult loginAction_init() {
        log.debug("-----------------loginloginAction_init start-----------------------");
        QueryResult rs = new QueryResult();
        HttpGet get = null;

        try {
            get = getGet(Consts.URL_loginAction_init);
//        get.addHeader(Consts.Accept_Header, Consts.Accept);
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
            get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            get.addHeader(Consts.Connection_Header, Consts.Connection);
            get.addHeader(Consts.Host_Header, Consts.Host);
//        get.addHeader(Consts.User_Agent, Consts.UserAgent_Default);
            get.addHeader(Consts.Referer_Header, "https://dynamic.12306.cn/otsweb/main.jsp");

            String responseBody = getHttpclient().execute(get, new BasicResponseHandler());
            String info = Util.removeTagFromHtml(responseBody);
//            log.debug(info);

//            log.info(info);
            rs.setMsg(info);
            rs.setRawData(responseBody);
            rs.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        } finally {
            get.releaseConnection();
        }
        log.debug("-------------------loginloginAction_init end---------------------");
        return rs;
    }

    /**
     *
     */
    public String loginAction_loginAysnSuggest() {
        log.debug("-----------------loginloginAction_init start-----------------------");
        QueryResult rs = new QueryResult();
        HttpPost post = null;

        String response = null;
        try {
            post = getPost(Consts.URL_loginAction_loginAysnSuggest);
            post.addHeader(Consts.Accept_Header, "application/json, text/javascript, */*");
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
            post.addHeader("Cache-Control", "no-cache");
            post.addHeader(Consts.Connection_Header, Consts.Connection);
            post.addHeader(Consts.Host_Header, Consts.Host);
            post.addHeader("Pragma", "no-cache");
            post.addHeader(Consts.Referer_Header, "https://dynamic.12306.cn/otsweb/loginAction.do?method=login");
            post.addHeader("X-Requested-With", "XMLHttpRequest");

            response = getHttpclient().execute(post, new BasicResponseHandler());

            log.info(response);

            rs.setMsg(response);
            rs.setRawData(response);
            rs.setState(QueryResult.SUCC);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        } finally {
            post.releaseConnection();
        }

        String loginRand = null;
        try {
            JSONObject json = new JSONObject(response);
            loginRand = json.get("loginRand").toString();
        } catch (JSONException ex) {
            log.info(response);
            log.error(ex.getLocalizedMessage(), ex);
        }
        log.info("loginRand: {}", loginRand);
        log.debug("-------------------loginloginAction_init end---------------------");
        return loginRand;
    }

    /**
     * 获取指定url的验证码图片字节信息
     *
     * @param url
     * @return
     */
    public byte[] getRandCodeBytes(String url) {
        log.debug("-------------------get randcode start-------------------");
        HttpGet get = getGet(url + "&" + random.nextDouble());
        get.addHeader(Consts.Accept_Header, "image/png,image/*;q=0.8,*/*;q=0.5");
//        get.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        get.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
//        get.addHeader(Consts.Connection_Header, Consts.Connection);
        get.addHeader(Consts.Host_Header, Consts.Host);
        if (url.indexOf("sjrand") > 0) {    //it's login
            get.addHeader(Consts.Referer_Header, "https://dynamic.12306.cn/otsweb/loginAction.do?method=init");
        } else if (url.indexOf("randp") > 0) {  //order
            get.addHeader(Consts.Referer_Header, "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init");
            //?cookies?
        }
        byte[] result = null;
        try {
            ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() {
                public byte[] handleResponse(
                        HttpResponse response) throws ClientProtocolException, IOException {
                    HttpEntity entity = response.getEntity();
                    try {
                        if (entity != null) {
                            return EntityUtils.toByteArray(entity);
                        } else {
                            return null;
                        }
                    } finally {
                        EntityUtils.consume(entity);
                    }
                }
            };
            result = getHttpclient().execute(get, handler);
            log.info("image length: {}", result.length);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        } finally {
            try {
                get.releaseConnection();
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        }
        log.debug("-------------------get randcode end-------------------");
        return result;
    }

    /**
     * 获取验证码
     */
    public String getRandCodeDailog_old(final String url) {
        byte[] image = getRandCodeBytes(url);
        JLabel label = new JLabel("", JLabel.CENTER);
        label.setIcon(new ImageIcon(image));
        label.setText(OCR.doOCR(image));

        label.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                byte[] image = getRandCodeBytes(url);
                String randCodeByOCR = OCR.doOCR(image);
                JLabel label = (JLabel) e.getSource();
                label.setIcon(new ImageIcon(image));
                label.setText(randCodeByOCR);
            }
        });

        return JOptionPane.showInputDialog(null, label, "请输入验证码", JOptionPane.DEFAULT_OPTION);
    }

    public QueryResult login() {
        return login(currentUser, pwd, loginAction_loginAysnSuggest(),
                getRandCodeDailog(Consts.URL_passCodeAction_rand_login));
    }

    public boolean checkLogin() {
        setTimeout();
        while (!isLoginOk()) {
            login();
        }
        return isLoginOk();
    }

    public synchronized String getCookies() {
        List<Cookie> cookies = ((DefaultHttpClient) getHttpclient()).getCookieStore().getCookies();
        StringBuilder sb = new StringBuilder();
        for (Cookie cookie : cookies) {
//            log.info("Cookie: {} : {}", cookie.getName(), cookie.getValue());
            sb.append(String.format(";%s=%s", cookie.getName(), cookie.getValue()));
        }
        return sb.toString().replaceFirst(";", "").replace(";", "; ");
    }

    public String getCookieValue(String key) {
        List<Cookie> cookies = ((DefaultHttpClient) getHttpclient()).getCookieStore().getCookies();
        String result = "";
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(key)) {
                result = cookie.getValue();
                break;
            }
        }
        return result;
    }

    /**
     * login
     *
     * @param username
     * @param password
     * @param randCode
     * @return
     */
    public QueryResult login(String username, String password, String randCode, String randstr) {
        log.debug("-----------------login start-----------------------");

        QueryResult rs = new QueryResult();

        HttpPost httppost = getPost(Consts.URL_loginAction_login);

        httppost.addHeader(Consts.Accept_Header, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//        httppost.addHeader(Consts.Accept_Encoding, Consts.AcceptEncoding);
//        httppost.addHeader(Consts.Accept_Language, Consts.AcceptLanguage);
        httppost.addHeader(Consts.Connection_Header, Consts.Connection);
        httppost.addHeader(Consts.Host_Header, Consts.Host);
        httppost.addHeader(Consts.Referer_Header, "https://dynamic.12306.cn/otsweb/loginAction.do?method=init");

        List<NameValuePair> parameters = new ArrayList<NameValuePair>();
        parameters.add(new BasicNameValuePair("loginRand", randstr));
        parameters.add(new BasicNameValuePair("loginUser.user_name", username));
        parameters.add(new BasicNameValuePair("nameErrorFocus", ""));
        parameters.add(new BasicNameValuePair("passwordErrorFocus", ""));
        parameters.add(new BasicNameValuePair("randCode", randCode));
        parameters.add(new BasicNameValuePair("randErrorFocus", "focus"));
        parameters.add(new BasicNameValuePair("refundFlag", "Y"));
        parameters.add(new BasicNameValuePair("refundLogin", "N"));
        parameters.add(new BasicNameValuePair("user.password", password));
        String responseBody = null;
        try {
            UrlEncodedFormEntity uef = new UrlEncodedFormEntity(parameters, HTTP.UTF_8);
            httppost.setEntity(uef);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            responseBody = getHttpclient().execute(httppost, responseHandler);
            String info = Util.removeTagFromHtml(responseBody)
                    .replace("\r\n", "").replace("\r", "").replace("\n", "");
            log.debug("-----------------------------------------------------");
            log.debug(info);
            log.debug("-----------------------------------------------------\n\n\n\n\n");
            rs.setRawData(responseBody);
            if (responseBody.contains(Constants.USER_LOCKED)) {
                log.error("用户:" + username + Constants.USER_LOCKED);
                rs.setState(QueryResult.USER_LOCKED);
                rs.setMsg(Constants.USER_LOCKED);
            } else if (responseBody.contains(Constants.USER_NOT_EXIST)) {
                log.error("用户:" + username + Constants.USER_NOT_EXIST);
                rs.setState(QueryResult.ACC_ERROR);
                rs.setMsg(Constants.USER_NOT_EXIST);
            } else if (info.contains(Constants.USER_PWD_ERR)) {
                log.error("用户:" + username + Constants.USER_PWD_ERR);
                rs.setState(QueryResult.PWD_ERROR);
                rs.setMsg(Constants.USER_PWD_ERR);
            } else if (info.contains(Constants.USER_SUCC_INFO2)) {
                int index = responseBody.indexOf("-->");
                log.debug(responseBody.substring(index + 4));
                rs.setState(QueryResult.SUCC);
                rs.setMsg(Constants.LOGIN_SUC);
                this.loginOk = true;
                this.currentUser = username;
                this.pwd = password;
                log.info(getCookies());
            } else if (info.contains(Constants.CODE_ERROR)) {
                log.warn("用户:" + username + Constants.CODE_ERROR);
                rs.setState(QueryResult.RAND_CODE_ERROR);
                rs.setMsg(Constants.CODE_ERROR);
            } else if (responseBody.contains(Constants.LOGIN_ERR_INFO)) {
                log.info("用户:" + username + Constants.USER_RELOGIN);
                rs.setState(QueryResult.LOGIN_ERROR);
                rs.setMsg(Constants.USER_RELOGIN);
            } else if (responseBody.contains(Constants.LOGIN_LOSTS_POEPLE)) {
                log.info("用户:" + username + Constants.LOGIN_LOSTS_POEPLE);
                rs.setState(QueryResult.LOST_OF_PEOPLE);
                rs.setMsg(Constants.LOGIN_LOSTS_POEPLE);
            } else {
                log.info("用户:" + username + Constants.UNKNOW_ERROR);
                rs.setState(QueryResult.OTHER);
                rs.setMsg(Constants.UNKNOW_ERROR);
                System.out.println(responseBody);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        } finally {
            httppost.releaseConnection();
        }
        log.debug("-------------------login end---------------------");
        return rs;
    }

//</editor-fold>  
    public void writetoFile(String path, String content) {
        FileWriter fw = null;
        try {
            fw = new FileWriter(path);
            fw.write(content);
            fw.flush();
            fw.close();
        } catch (Exception ex) {
            log.error(ex.getLocalizedMessage(), ex);
        } finally {
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (Exception ex) {
            }
        }
    }
    /**
     * loginOk set to true when login ok.
     */
    private boolean loginOk = false;

    /**
     * @return the loginOk
     */
    public synchronized boolean isLoginOk() {
        return loginOk;
    }

    /**
     * @return the httpclient
     */
    public HttpClient getHttpclient() {
        return httpClient;
    }

    /**
     * @param httpclient the httpclient to set
     */
    public void setHttpclient(HttpClient httpclient) {
        this.httpClient = httpclient;
    }

    /**
     * @return the userName
     */
    public String getCurrentUser() {
        return currentUser;
    }

    /**
     * @return the pwd
     */
    public String getPwd() {
        return pwd;
    }

    /**
     * @param loginOk the loginOk to set
     */
    public synchronized void setTimeout() {
        this.loginOk = false;
    }

    /**
     * @return the userAgent
     */
    public String getUserAgent() {
        if (userAgent == null || userAgent.isEmpty()) {
            userAgent = Consts.UserAgent_Default;
        }
        return userAgent;
    }

    /**
     * @param userAgent the userAgent to set
     */
    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }

    public void setCookies(String big, String session) {
        List<Cookie> cookies = ((DefaultHttpClient) httpClient).getCookieStore().getCookies();

        ((DefaultHttpClient) httpClient).getCookieStore().clear();
        for (Cookie cookie1 : cookies) {
            BasicClientCookie cookie = (BasicClientCookie) cookie1;
            if (cookie.getName().equals("BIGipServerotsweb")) {
                cookie.setValue(big);
            } else if (cookie.getName().equals("JSESSIONID")) {
                cookie.setValue(session);
            }
            ((DefaultHttpClient) httpClient).getCookieStore().addCookie(cookie);
        }
    }
}